package org.moonlight.jvm.instructions.references;

import org.moonlight.jvm.instructions.base.Index16Instruction;
import org.moonlight.jvm.rtda.exclusive.Frame;
import org.moonlight.jvm.rtda.share.heap.Class;
import org.moonlight.jvm.rtda.share.heap.symref.ClassRef;
import org.moonlight.jvm.rtda.share.methodarea.RtConstantPool;
import org.moonlight.jvm.rtda.share.Object;
/**
 * new: 专门用来创建对象，但数组除外，数组有专门的指令创建。
 *      new指令的操作数是一个uint16索引，来自字节码。通过这个索引，可以从当前类的运行时常量池中找到一个类符号引用。
 *      解析这个类符号引用，拿到类数据，然后创建对象，并把对象引用推入栈顶，new指令的工作就完成了。
 *
 * @author Moonlight
 * @createTime 2023/8/30 13:58
 **/
public class New extends Index16Instruction {

    @Override
    public void execute(Frame frame) {
        // 通过一个uint16索引从当前类的运行时常量池中找到一个类符号引用
        RtConstantPool rtCp = frame.getMethod().getClazz().getRtCp();
        ClassRef classRef = (ClassRef) rtCp.getConstant(this.idx);
        // 解析这个类符号引用，拿到类数据
        Class clazz = classRef.resolvedClass();
        // 如果类还没有经过类初始化，那么需要先经过类初始化
        // 类初始化时，先终止当前指令的执行，并将当前栈帧的nextPc重置指向当前指令
        if (!clazz.isInitStarted()) {
            frame.revertNextPc();
            clazz.classInit(frame.getThread());
            return;
        }

        if (clazz.isAbstract() || clazz.isInterface()) {
            throw new InstantiationError();
        }
        // 然后创建对象，并把对象引用推入栈顶
        Object ref = clazz.newObject();
        frame.getOperandStack().pushRef(ref);
    }

}